﻿using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Net;
using Liber;
using System.IO;
using Liber.WEB;
using Liber.ORM;
using HtmlAgilityPack;
using ExpertPdf.HtmlToPdf;
using AgileAgent.cn.com.agile;

namespace AgileAgent.Controllers
{
    public class AgileAgentController : LiberAgent
    {
        static MSSQLHelper DBHelper = new MSSQLHelper("");
        static string myerpCnnStr = "";

        public AgileAgentController() : base()
        {
            Ini("518518bug_20151212sobiz", "77954376886386987", "a90e0a017ff3ac412a32hu18854907gx", "https://211.149.249.166");
            if (myerpCnnStr == "")
            {
                var cnns = XMLSetting.DefaultSetting.First("DBConnection").All("Connection");
                var lnk = XMLSetting.DefaultSetting.First("DBConnection").First("Default").Value;
                foreach (var cn in cnns)
                {
                    if (cn.Property("Name") == lnk)
                    {
                        myerpCnnStr = cn.Value;
                        break;
                    }
                }
            }
        }

        public ViewResult Index()
        {
            return View();
        }

        /// <summary>
        /// 转换Html文档为Pdf并上传为业务数据相关的文档
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="nonce"></param>
        /// <param name="singanature"></param>
        /// <param name="objid"></param>
        /// <param name="objver"></param>
        /// <returns></returns>
        [NoSession]
        public JsonResult ConvertOpenBizHtml2Pdf(string docType = "", string objid = "", string objver = "", string ignoreElm = "", bool overide = true)
        {
            WinEventLog("开始转换订单合同文本："+ objid+":"+objver,"info");
            var html = new HtmlDocument();
            html.OptionOutputOriginalCase = true;
            html.OptionWriteEmptyNodes = true;
            html.OptionAutoCloseOnEnd = true;
            
            try
            {
                if (Request.InputStream.Length == 0)
                {
                    return Json(null);
                }
                html.Load(Request.InputStream);
                try {
                    //删除指定节点
                    var ies = ignoreElm.Split(',');
                    foreach (var s in ies)
                    {
                        if (!string.IsNullOrEmpty(s))
                        {
                            if (html.GetElementbyId(s) != null)
                            {
                                html.GetElementbyId(s).Remove();
                            }
                        }
                    }
                }
                catch
                {

                }       

                try
                {
                    var data = Convert2(html);

                    //将转换的pdf文档再上传到标准上传接口
                    string nonce = new Random().Next(int.MaxValue).ToString();
                    string appid = "77954376886386987";
                    //string singanature = (appid + "a90e0a017ff3ac412a32hu18854907gx" + nonce).SHA1();  奇怪，在雅居乐这边SHA1中的+号都被替换为空格了
                    string singanature = (appid + "a90e0a017ff3ac412a32hu18854907gx" + nonce).MD5Encrypt();
                    string upUrl = "https://tlunion.com/File/UploadOpenBizDoc?appid=" + appid;
                    upUrl += "&nonce=" + nonce;
                    upUrl += "&singanature=" + singanature;
                    upUrl += "&docType=" + docType;
                    upUrl += "&objid=" + objid;
                    upUrl += "&objver=" + objver;
                    upUrl += "&fileType=pdf";
                    upUrl += "&overide=" + overide;

                    Uri upDocUrl = null;
                    Uri.TryCreate(upUrl, UriKind.Absolute, out upDocUrl);
                    var rtn= new WebClient().UploadData(upDocUrl, data);
                    string rtnStr = System.Text.Encoding.UTF8.GetString(rtn);
                    if (rtnStr.IndexOf("true")<0)
                    {
                        //上传失败
                        WinEventLog("上传失败：" + objid + ":" + objver);
                        //TODO:上传失败，等待重试
                        return Json(FnResult.Failure("AgileAgentController","UploadBizDocFailure").SetError("error",rtnStr));
                    }
                    else
                    {
                        return Json(FnResult.Sucess(null));
                    }

                }
                catch (WebException ex)
                {
                    WinEventLog("Web上传失败："+ex.Message);
                    return Json(FnResult.Failure("AgileAgentController", "UploadFailure").SetError("exception", ex.Message));
                }
                finally
                {
                    
                }
            }
            catch (Exception ex)
            {
                WinEventLog("转换并上传时发生未捕获异常："+ex.Message);
                return Json(FnResult.Failure("AgileAgentCountrller", "ConvertFailure").SetError("exception", ex.Message));
            }
            finally
            {

            }
        }

        public byte[] Convert2(HtmlDocument html)
        {
            var cnvter = new ExpertPdf.HtmlToPdf.PdfConverter();
            cnvter.PdfDocumentOptions.EmbedFonts = false;
            cnvter.PdfDocumentOptions.GenerateSelectablePdf = true;
            cnvter.PdfDocumentOptions.InternalLinksEnabled = true;
            cnvter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel.NoCompression;
            cnvter.PdfSecurityOptions.CanAssembleDocument = false;
            cnvter.PdfSecurityOptions.CanEditContent = false;
            cnvter.PdfSecurityOptions.CanFillFormFields = false;
            cnvter.PdfSecurityOptions.CanEditAnnotations = false;
            cnvter.TransparencyEnabled = false;
            cnvter.AlphaBlendEnabled = false;  //不能开启，否则在液晶屏幕上字体显得有些蒙
            cnvter.MaskBltEnabled = false;
            cnvter.OptimizePdfPageBreaks = true;
            cnvter.OptimizeMemoryUsage = true;

            return cnvter.GetPdfBytesFromHtmlString(html.DocumentNode.OuterHtml);
        }


        protected override List<ERPPurchaseOrder> PurchaseNewOrder(DateTime startTime,ref DateTime endTime)
        {
            DBHelper = new MSSQLHelper(myerpCnnStr);
            var rtn = new List<ERPPurchaseOrder>();
            try
            {
                var data = new List<DyObject>();

                    data = DBHelper.Query(string.Format(@"SELECT  
                                            A.CgIndentGuid AS ID,
                                            A.PreCgIndentGUID AS PreID,
                                            A.TaxRate,
                                            A.TaxTypeName,
                                            '明细' as InvoiceMX,
		                                    A.VersionCode AS Version,
		                                    A.CgIndentCode AS Serial,
		                                    A.InvoiceHeading AS InvoiceHeading,
		                                    B.ProviderName AS Supplier,
		                                    A.Primaryer AS Saler,
		                                    A.Phone AS SalerPhone,
		                                    A.JhDate AS DeliveryDate,
		                                    A.JhAddress AS DeliveryAddress,
		                                    C.ContractCode AS ContractNO,
		                                    A.Consignee AS Consignee,
		                                    A.ConsigneePhone AS ConsigneePhone,
		                                    A.Jbr AS Buyer,
		                                    A.JbrPhone+'/'+u.MobilePhone AS BuyerPhone,
		                                    A.ShType AS DeliveryMode,
		                                    A.BalanceType+' | 材料预付订金比例'+CONVERT(NVARCHAR(10),CLYfRate)+'材料进度款比例'+CONVERT(NVARCHAR(10),CLScheduleRate)+'材料质保金比例'+CONVERT(NVARCHAR(10),CLBxRate) AS Settlement,
		                                    '有，自货品验收合格后 1 年内免费保修' AS QualityGuarantee,
		                                    A.Remarks AS Memo,
		                                    A.IndentAmount AS Amount,
		                                    A.IndentSdType AS Receipt,
		                                    A.IndentDate AS OrderDate,
		                                    A.ApproveDate AS PublishTime,
                                            A.SgYfProviderNameList AS Constructor,
                                            A.FbYfProviderName AS SubConstructor,
                                            A.ApplySubjectList AS BuyFor
	                                    FROM cb_CgIndent A
	                                    INNER JOIN p_Provider B ON B.ProviderGuid=A.CgPlanProviderGuid
	                                    LEFT JOIN cb_Contract C ON C.ContractGuid=A.ContractGuid
                                        LEFT JOIN myUser u ON u.UserGUID=A.JbrGUID
                                        WHERE B.ProviderName <> '中山市雅丰贸易有限公司'
                                        AND A.ApproveDate>'{0}'
                                        ORDER BY A.ApproveDate DESC
                                        ", startTime));
                
                foreach (var d in data)
                {
                    ERPPurchaseOrder o = new ERPPurchaseOrder();
                    o.ID = d["ID"].ToString();
                    o.PreID = d["PreID"].ToString();
                    o.Version = d["Version"].ToString();
                    o.Serial = d["Serial"].ToString();
                    o.InvoiceHeading = d["InvoiceHeading"].ToString();
                    o.Client = o.InvoiceHeading;  //当前订单发出单位，也即供应商眼中的客户，怎么取？对于雅居乐，由于其ERP缺少真正的用户所属公司名称信息，直接用invoiceheading
                    o.Supplier = d["Supplier"].ToString();
                    o.Saler = d["Saler"].ToString();
                    o.SalerPhone = d["SalerPhone"].ToString();   //可能有多个，/分割
                    o.DeliveryDate = d["DeliveryDate"].ToString();
                    o.DeliveryAddress = d["DeliveryAddress"].ToString();
                    o.ContractNO = d["ContractNO"].ToString();
                    o.Consignee = d["Consignee"].ToString();   //可能多人，/分割
                    o.ConsigneePhone = d["ConsigneePhone"].ToString();   //可能多个，/分割
                    o.Buyer = d["Buyer"].ToString();
                    o.BuyerPhone = d["BuyerPhone"].ToString();
                    o.DeliveryMode = d["DeliveryMode"].ToString();
                    o.Settlement = d["Settlement"].ToString();
                    o.QualityGuarantee = d["QualityGuarantee"].ToString();   //写在表单上，没法取
                    o.Memo = d["Memo"].ToString();
                    o.Amount = d["Amount"].ToString();
                    o.Receipt = string.IsNullOrEmpty(d["Receipt"].ToString()) ? "天联云平台" : d["Receipt"].ToString()+"/天联云平台";
                    o.OrderDate = d["OrderDate"].ToString();
                    o.PublishTime = d["PublishTime"].ToString();
                    o.TaxRate = d["TaxRate"].ToString();
                    o.InvoiceType = d["TaxTypeName"].ToString();
                    o.InvoiceMX = d["InvoiceMX"].ToString();
                    o.Constructor = d["Constructor"].ToString();
                    o.SubConstructor = d["SubConstructor"].ToString();
                    o.BuyFor = d["BuyFor"].ToString();

                    o.OrderItems = PurchaseOrderMX(o.ID);
                    rtn.Add(o);
                }
                if (data.Count > 0)
                {
                    endTime = DateTime.Parse(data[0]["PublishTime"].ToString());
                }
                else
                {
                    endTime = startTime;
                }        
            }
            catch (Exception ex)
            {
                rtn = new List<ERPPurchaseOrder>();
                WinEventLog(ex.Message);
            }
            return rtn;
        }

        List<ERPPurchaseOrderMX> PurchaseOrderMX(string orderid)
        {
            DBHelper = new MSSQLHelper(myerpCnnStr);
            var rtn = new List<ERPPurchaseOrderMX>();
            try{
                var data = DBHelper.Query(@"SELECT
                                                A.CgIndentProductGUID AS ID,
	                                            A.CgIndentGUID AS OrderID,
                                                B.ProductCode,
	                                            B.ProductName,
	                                            B.MakeBy,
	                                            B.TypeNo,
	                                            B.ProductSpec,
	                                            A.IndentQty,
	                                            B.Unit,
	                                            A.Price,
	                                            A.Amount,
	                                            A.Remarks,
                                                C.ApproveDate
                                            FROM
	                                            cb_CgIndentProduct A
                                            INNER JOIN p_Product B ON B.ProductGuid = A.ProductGuid
                                            INNER JOIN cb_CgIndent C ON A.CgIndentGUID=C.CgIndentGUID AND C.CgIndentGUID='"+orderid+"'");

                foreach (var d in data)
                {
                    ERPPurchaseOrderMX o = new ERPPurchaseOrderMX();
                    o.ID = d["ID"].ToString();
                    o.OrderID = d["OrderID"].ToString();
                    o.Name = d["ProductName"].ToString();
                    o.Brand = d["MakeBy"].ToString();
                    o.Model = d["TypeNo"].ToString();
                    o.Specification = d["ProductSpec"].ToString();
                    o.Count = d["IndentQty"].ToString();
                    o.Unit = d["Unit"].ToString();
                    o.Price = d["Price"].ToString();
                    o.Amount = d["Amount"].ToString();
                    o.Memo = d["Remarks"].ToString();
                    o.Code = d["ProductCode"].ToString();
                    rtn.Add(o);
                }
            }
            catch(Exception ex){
                WinEventLog("查询订单明细数据时发生错误"+ex.Message);
            }
            return rtn;       
        }

        protected override List<ERPSumOrderStockIn> OrderStockSum(DateTime startTime,ref DateTime endTime)
        { 
            DBHelper = new MSSQLHelper(myerpCnnStr);
            var rtn = new List<ERPSumOrderStockIn>();
            try
            {
                var sDate = startTime.Date;
                //TODO:正式上线后，为减少资源消耗，库存数据每天同步一次，且只在每天上午9点
                if (DateTime.Now.Hour<9)
                {
                    return rtn;
                }

                var data = DBHelper.Query(string.Format(@"SELECT SUM(cedd.Quantity) as totalStockIn,cedd.CgIndentProductGUID as ordermxid,MAX(cedb.ApproveDate) as lastApproveDate from cb_EnterDepotDtl cedd
                                                            JOIN cb_EnterDepotBill cedb on cedb.EnterDepotBillGUID=cedd.EnterDepotBillGUID
                                                            WHERE EXISTS(
	                                                            SELECT 1 from cb_EnterDepotBill cedb2
	                                                            JOIN vcb_CgIndent ci on ci.CgIndentGUID=cedb2.CgIndentGUID and ci.ProviderName<>'中山市雅丰贸易有限公司'
	                                                            where cedb2.ApproveDate>'{0}'
                                                                AND cedb2.ApproveDate<'{1}' 
                                                                and cedb2.CgIndentGUID=cedb.CgIndentGUID
                                                            )
                                                            GROUP BY cedd.CgIndentProductGUID
                                                            ORDER BY lastApproveDate DESC", sDate.ToShortDateString(),DateTime.Today.ToShortDateString()));
                                                            //排除当天的订单，避免出现：早上9点前抓了一次后，当天的其他入库单就永远抓不到了
                foreach (var d in data)
                {
                    ERPSumOrderStockIn o = new ERPSumOrderStockIn();
                    o.OrderMXID = d["ordermxid"].ToString();
                    o.TotalStockIn = d["totalStockIn"].ToString();
                    rtn.Add(o);
                }
                if (data.Count > 0)
                {
                    endTime = DateTime.Parse(data[0]["lastApproveDate"].ToString());
                }
                else
                {
                    endTime = sDate;
                }
            }
            catch (Exception ex)
            {
                rtn = new List<ERPSumOrderStockIn>();
                WinEventLog("查询订单累计入库数据时发生错误" + ex.Message);
            }
            return rtn;
        }

        protected override List<ERPSumOrderStockIn> OrderStockSum(string orderGUID)
        {
            DBHelper = new MSSQLHelper(myerpCnnStr);
            var rtn = new List<ERPSumOrderStockIn>();
            try
            {
                var data = DBHelper.Query(string.Format(@"SELECT SUM(cedd.Quantity) as totalStockIn,cedd.CgIndentProductGUID as ordermxid,MAX(cedb.ApproveDate) as lastApproveDate from cb_EnterDepotDtl cedd
                                                            JOIN cb_EnterDepotBill cedb on cedb.EnterDepotBillGUID=cedd.EnterDepotBillGUID
                                                            WHERE EXISTS(
	                                                            SELECT 1 from cb_EnterDepotBill cedb2
	                                                            JOIN vcb_CgIndent ci on ci.CgIndentGUID=cedb2.CgIndentGUID and ci.ProviderName<>'中山市雅丰贸易有限公司'
	                                                            where cedb2.CgIndentGUID=cedb.CgIndentGUID and cedb2.CgIndentGUID='{0}'
                                                            )
                                                            GROUP BY cedd.CgIndentProductGUID
                                                            ORDER BY lastApproveDate DESC", orderGUID));

                foreach (var d in data)
                {
                    ERPSumOrderStockIn o = new ERPSumOrderStockIn();
                    o.OrderMXID = d["ordermxid"].ToString();
                    o.TotalStockIn = d["totalStockIn"].ToString();
                    rtn.Add(o);
                }
            }
            catch (Exception ex)
            {
                WinEventLog("查询指定订单的累计入库数据时发生错误" + ex.Message);
            }
            return rtn;
        }

        protected override List<ERPPurchaseOrderState> OrderStateChange(DateTime startTime,ref DateTime endTime)
        {
            DBHelper = new MSSQLHelper(myerpCnnStr);
            var rtn = new List<ERPPurchaseOrderState>();
            try
            {
                var data = DBHelper.Query(string.Format(@"SELECT cor.BusinessGUID as orderid,cor.OprDate,cor.Opr,cor.OprType,cor.Remarks from cb_CgOprRecord cor 
                                                          JOIN vcb_CgIndent cci on cci.CgIndentGUID=cor.BusinessGUID and cci.ProviderName<>'中山市雅丰贸易有限公司'                                                          
                                                          WHERE (cor.OprType='结束订货单' or cor.OprType='取消结束订货单')
                                                          AND cor.OprDate>'{0}'
                                                          ORDER BY cor.OprDate DESC", startTime.ToString()));

                foreach (var d in data)
                {
                    ERPPurchaseOrderState o = new ERPPurchaseOrderState();
                    o.OrderID = d["orderid"].ToString();
                    o.OpreatTime = d["OprDate"].ToString();
                    o.OpreatType = d["OprType"].ToString()=="结束订货单"?"CloseOrder":"ReactiveOrder";
                    o.Opreater = d["Opr"].ToString();
                    o.Remark = d["Remarks"].ToString();
                    rtn.Add(o);
                }
                if (data.Count > 0)
                {
                    endTime = DateTime.Parse(data[0]["OprDate"].ToString());
                    endTime = endTime.AddSeconds(1);  //增加1秒，避免由于erp中精确度导致最后一条被重复抓取
                }
                else
                {
                    endTime = startTime.AddMinutes(-1);
                }
            }
            catch (Exception ex)
            {
                rtn = new List<ERPPurchaseOrderState>();
                WinEventLog("查询订单操作日志时发生错误" + ex.Message);
            }
            return rtn;
        }

        protected override string DoNewReceipt(string msg)
        {
            var erpAPI = XMLSetting.DefaultSetting.First("ErpAPI").First("OnNewReceipt", false);
            if (erpAPI == null)
            {
                return "";
            }
            else
            {
                //将云端传来的数据转换为雅居乐所需的格式
                var srcEvent = XMLSetting.LoadFromStr(msg);

                var toEvent = XMLSetting.LoadFromStr("<XML></XML>");
                toEvent.First("CgIndentGUID").Value = srcEvent.First("SrcOrderID").Value; //源订单GUID
                toEvent.First("DlvID").Value = srcEvent.First("DlvBillID").Value;  //云平台发货单ID
                toEvent.First("Consignee").Value = srcEvent.First("Receipter").Value;  //收货人
                toEvent.First("ConsigneeDate").Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");  //收货时间
                toEvent.First("DlvRemark",true,true).Value = srcEvent.First("DlvRemark").Value;  //发货备注

                var itms = toEvent.First("ReceiptItems",true);
                foreach(var itm in srcEvent.First("ReceiptItems").All("Item"))
                {
                    itms.Append("Item", false).SetFirst("CgIndentProductGUID", itm.First("OrderMXID").Value)  //发货单明细对应的源订单明细ID
                                                        .SetFirst("RcvCount", itm.First("ReceiptCount").Value)   //收货数量
                                                        .SetFirst("RcvRemark", itm.First("MXRemark").Value,true);            //收货备注
                }

                //return @"<XML>
                //            <Bill>
                //                <BillGUID>guid</BillGUID>
                //                <BillType>雅丰入库单</BillType>
                //            </Bill>
                //            <Bill>
                //                <BillGUID>guid</BillGUID>
                //                <BillType>雅丰入库单</BillType>
                //            </Bill>
                //        </XML>";

                //将数据推送到配置的ERP接口，并接收返回值
                string url = erpAPI.Value;
                string rsp = "";

                var wsl = new GetJtContractService();
                wsl.Url = url;
                rsp=wsl.CreateDepotInfo(toEvent.InnerXML);

                //rsp = WebHelper.PostDataTo(url, toEvent.InnerXML);
                toEvent.Dispose();
                return rsp;
            }
        }
    }
}